package com.cloud.school.app.controller;

import com.cloud.school.app.config.security.JWTUtils;
import com.cloud.school.app.config.security.SecurityUserDetails;
import com.cloud.school.app.config.security.SecurityUserUtils;
import com.cloud.school.app.config.security.ValidateCode;
import com.cloud.school.app.model.FriendshipModel;
import com.cloud.school.app.model.UserModel;
import com.cloud.school.app.model.UserNewData;
import com.cloud.school.app.service.FriendshipService;
import com.cloud.school.app.service.UserService;
import com.cloud.school.app.service.impl.CacheService;
import com.cloud.school.app.util.ResponseUtil;
import com.cloud.school.app.util.enumeration.FriendshipStatus;
import com.cloud.school.app.util.enumeration.UserStatus;
import com.google.common.collect.Sets;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.cloud.school.app.config.SecurityConfiguration.ROLE_USER;
import static com.cloud.school.app.config.security.JWTUtils.*;
import static com.cloud.school.app.config.security.SecurityUserUtils.LOGIN_USER;
import static com.cloud.school.app.service.impl.AnswerServiceImpl.USER_NEW_ANSWER;
import static com.cloud.school.app.service.impl.ChatWebSocketHandler.USER_ID_SESSION_ID_MAP_KEY;
import static com.cloud.school.app.service.impl.CommentServiceImpl.USER_NEW_COMMENT;
import static com.cloud.school.app.service.impl.MessageServiceImpl.USER_NEW_MESSAGE;

/**
 * @ClassName UserController
 * @Description TODO
 * @Author 36297
 * @Date 2018/12/1 15:07
 * @Version 1.0
 */
@Api(tags = "用户中心控制器")
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private CacheService cacheService;
    @Autowired
    private UserService userService;
    @Autowired
    private FriendshipService friendshipService;

    @ApiOperation("用户登录")
    @RequestMapping(value = "/login", method = RequestMethod.GET)
    public ResponseUtil<String> login(@ApiParam("用户手机号") @RequestParam String telephone, @ApiParam("验证码") @RequestParam String code, HttpServletResponse response) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(telephone, code);
        try {
            Authentication authentication = authenticationManager.authenticate(authenticationToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            cacheService.put(LOGIN_USER + telephone, "isLogin");
            cacheService.expire(LOGIN_USER + telephone, tokenRefreshTimeInDays, TimeUnit.DAYS);
            //获取用户信息
            SecurityUserDetails userDetails = new SecurityUserDetails(SecurityUserUtils.getCurrentUserId(), telephone, Sets.newHashSet(ROLE_USER));
            String jwt = JWTUtils.createToken(userDetails);
            response.addHeader(AUTHORIZATION_HEADER, AUTHORIZATION_HEADER_BEARER + jwt);
            return ResponseUtil.ok(jwt);
        } catch (BadCredentialsException be) {
            return ResponseUtil.fail("手机号或验证码错误");
        } catch (AuthenticationException ae) {
            return ResponseUtil.fail("登录验证失败");
        }
    }

    @ApiOperation("新用户注册草稿(暂存用户信息使用)")
    @RequestMapping(value = "/draft", method = RequestMethod.POST)
    public ResponseUtil<Boolean> draft(@RequestBody UserModel userModel) {
        userModel.setStatus(UserStatus.UNREGISTER.getCode());
        return ResponseUtil.ok(userService.save(userModel));
    }

    @ApiOperation("新用户注册提交(注册用户使用)")
    @RequestMapping(value = "/submit", method = RequestMethod.POST)
    public ResponseUtil<Boolean> submit(@RequestBody UserModel userModel) {
        //判断验证码是否正确
        if (!ValidateCode.validateCode(userModel.getValidateCode(), userModel.getCellPhoneNum(), cacheService)) {
            return ResponseUtil.fail("验证码错误！");
        }
        userModel.setStatus(UserStatus.REGISTER.getCode());
        return ResponseUtil.ok(userService.save(userModel));
    }

    @ApiOperation("更新用户信息")
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    public ResponseUtil<Boolean> update(@RequestBody UserModel userModel) {
        return ResponseUtil.ok(userService.update(userModel));
    }

    @ApiOperation("发送短信验证码")
    @RequestMapping(value = "/sendValidateCode", method = RequestMethod.GET)
    public ResponseUtil<Boolean> sendValidateCode(@ApiParam("用户手机号") @RequestParam String telephone) {
        ValidateCode.sendMessage(cacheService, telephone);
        return ResponseUtil.ok(true);
    }

    @ApiOperation("用户昵称是否存在,true存在，false不存在")
    @RequestMapping(value = "/isNickNameExist", method = RequestMethod.GET)
    public ResponseUtil<Boolean> isNickNameExist(@ApiParam("用户昵称") @RequestParam String nickName) {
        return ResponseUtil.ok(userService.isNickNameExist(nickName));
    }

    @ApiOperation("用户是否注册,true注册，false没有注册")
    @RequestMapping(value = "/isPhoneNumExist", method = RequestMethod.GET)
    public ResponseUtil<Boolean> isPhoneNumExist(@ApiParam("用户手机号") @RequestParam String telephone) {
        return ResponseUtil.ok(userService.isPhoneNumExist(telephone));
    }

    @ApiOperation("用户信息")
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    public ResponseUtil<UserModel> info(@ApiParam("用户id") @RequestParam Long userId) {
        return ResponseUtil.ok(userService.queryDetailById(userId));
    }

    @ApiOperation("查询当前登录人信息")
    @RequestMapping(value = "/myInfo", method = RequestMethod.GET)
    public ResponseUtil<UserModel> myInfo() {
        return ResponseUtil.ok(userService.queryDetailById(SecurityUserUtils.getCurrentUserId()));
    }

    @ApiOperation("用户信息")
    @RequestMapping(value = "/infos", method = RequestMethod.GET)
    public ResponseUtil<List<UserModel>> infos(@ApiParam("用户ids") @RequestParam List<Long> userIds) {
        return ResponseUtil.ok(userService.queryDetailByIds(userIds));
    }

    @ApiOperation("申请好友/推荐好友")
    @RequestMapping(value = "/applyFriend", method = RequestMethod.POST)
    public ResponseUtil<Boolean> applyFriend(@RequestBody FriendshipModel friendshipModel) {
        if (friendshipService.isFriendShipExist(friendshipModel.getFirstUid(), friendshipModel.getSecondUid())) {
            ResponseUtil.fail("好友关系已存在！");
        }
        friendshipModel.setCreateUid(SecurityUserUtils.getCurrentUserId());
        friendshipModel.setStatus(FriendshipStatus.UNHANDLED.getCode());
        return ResponseUtil.ok(friendshipService.save(friendshipModel));
    }

    @ApiOperation("通过好友")
    @RequestMapping(value = "/passFriend", method = RequestMethod.POST)
    public ResponseUtil<Boolean> passFriend(@ApiParam("好友记录id,不是用户id") @RequestParam Long friendshipId) {
        return ResponseUtil.ok(friendshipService.updateStatus(friendshipId, FriendshipStatus.HANDLED.getCode()));
    }

    @ApiOperation("查询好友(好友或好友申请)")
    @RequestMapping(value = "/queryFriend", method = RequestMethod.GET)
    public ResponseUtil<List<FriendshipModel>> queryFriend(@ApiParam("记录状态,1未处理2已处理") @RequestParam(defaultValue = "1") int status) {
        return ResponseUtil.ok(friendshipService.selectDetailByUidAndStatus(SecurityUserUtils.getCurrentUserId(), status));
    }

    @ApiOperation("查询在线好友")
    @RequestMapping(value = "/queryOnlineFriend", method = RequestMethod.GET)
    public ResponseUtil<List<FriendshipModel>> queryOnlineFriend() {
        List<FriendshipModel> list = friendshipService.selectDetailByUidAndStatus(SecurityUserUtils.getCurrentUserId(), FriendshipStatus.HANDLED.getCode());
        Set<String> userIds = cacheService.hashKeys(USER_ID_SESSION_ID_MAP_KEY);
        List<FriendshipModel> result = list.stream().filter(f -> userIds.contains(f.getSecondUid().toString())).collect(Collectors.toList());
        return ResponseUtil.ok(result);
    }

    @ApiOperation("查询新数据条数提示信息")
    @RequestMapping(value = "/queryNewData", method = RequestMethod.GET)
    public ResponseUtil<UserNewData> queryNewData() {
        List<String> newAnswerCounts = cacheService.hashValues(USER_NEW_ANSWER + SecurityUserUtils.getCurrentUserId());
        List<String> newCommentCounts = cacheService.hashValues(USER_NEW_COMMENT + SecurityUserUtils.getCurrentUserId());
        List<String> newMessageCounts = cacheService.hashValues(USER_NEW_MESSAGE + SecurityUserUtils.getCurrentUserId());
        int newAnswerCount = newAnswerCounts.stream().filter(a -> a != null).map(a -> Integer.valueOf(a)).reduce(0, (a, b) -> a + b);
        int newCommentCount = newCommentCounts.stream().filter(c -> c != null).map(c -> Integer.valueOf(c)).reduce(0, (a, b) -> a + b);
        int newMessageCount = newMessageCounts.stream().filter(m -> m != null).map(m -> Integer.valueOf(m)).reduce(0, (a, b) -> a + b);
        UserNewData result = new UserNewData();
        result.setNewAnswerCount(newAnswerCount);
        result.setNewCommentCount(newCommentCount);
        result.setNewMessageCount(newMessageCount);
        return ResponseUtil.ok(result);
    }
}
